package com.xhga.common.util;

import com.itextpdf.text.Document;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import com.itextpdf.tool.xml.XMLWorkerHelper;

import java.io.*;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;

/**
 * PDF工具类
 */
public class PdfUtil {

    /**
     * HTML 转 PDF
     * @param content     html内容
     * @param outPath     输出pdf路径
     * @return 是否创建成功
     */
    public static boolean html2Pdf(String content, String outPath) {
        try {
            Document document = new Document();
            PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(outPath));
            document.open();
            XMLWorkerHelper.getInstance().parseXHtml(writer, document,
                    new ByteArrayInputStream(content.getBytes()), Charset.forName("UTF-8"));
            document.close();
        } catch (Exception e) {
            System.out.println("生成模板内容失败"+e.fillInStackTrace());
            return false;
        }
        return true;
    }

    /**
     * HTML 转 PDF
     * @param content html内容
     * @return PDF字节数组
     */
    public static byte[] html2Pdf(String content) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            Document document = new Document();
            PdfWriter writer = PdfWriter.getInstance(document, outputStream);
            document.open();
            XMLWorkerHelper.getInstance().parseXHtml(writer, document,
                    new ByteArrayInputStream(content.getBytes()), Charset.forName("UTF-8"));
            document.close();
        } catch (Exception e) {
            System.out.println("------生成pdf失败-------");
            return null;
        }
        return outputStream.toByteArray();
    }

    /**
     * 编辑pdf
     *
     * 传入可编辑表单的pdf(表单中存在文本域,图片域...)
     * 加密
     * @param inputStream  输入文件流
     * @param dataParamMap 要插入得数据
     * @param imgParamMap  要插入得图片
     * @param userPass    打开pdf密码
     * @param ownerPass   编辑pdf密码
     * @param permissions 权限
     * @return PDF字节数组
     */
    public static byte[] exitPdf(InputStream inputStream, Map<String, String> dataParamMap, Map<String, Image> imgParamMap, String userPass, String ownerPass, int permissions) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            PdfUtil.exitPdf(inputStream, dataParamMap, imgParamMap, outputStream, true, userPass, ownerPass, permissions);
        } catch (Exception e) {
            System.out.println("--- exitPdf error ---" + e.fillInStackTrace());
        }
        return outputStream.toByteArray();
    }
    public static byte[] exitPdf(InputStream inputStream, Map<String, String> dataParamMap, Map<String, Image> imgParamMap) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            PdfUtil.exitPdf(inputStream, dataParamMap, imgParamMap, outputStream, false, null, null, 0);
        } catch (Exception e) {
            System.out.println("--- exitPdf error ---" + e.fillInStackTrace());
        }
        return outputStream.toByteArray();
    }


    /**
     * 编辑pdf
     *
     * 传入可编辑表单的pdf(表单中存在文本域,图片域...)
     *
     * @param inputStream  输入文件流
     * @param dataParamMap 要插入得数据
     * @param imgParamMap  要插入得图片
     * @param outPdfFilePath  输出文件路径
     * @return 是否创建成功
     */
    public static boolean exitPdf(InputStream inputStream, Map<String, String> dataParamMap, Map<String, Image> imgParamMap, String outPdfFilePath) {
        try {
            FileOutputStream outputStream = new FileOutputStream(outPdfFilePath);
            PdfUtil.exitPdf(inputStream, dataParamMap, imgParamMap, outputStream, false, null, null, 0);
        } catch (Exception e) {
            System.out.println("--- exitPdf error ---" + e.fillInStackTrace());
            return false;
        }
        return true;
    }

    /**
     * @param inputStream  输入文件流
     * @param dataParamMap 要插入得数据
     * @param imgParamMap  要插入得图片
     * @param outputStream 输出文件流
     * @param encryption  是否口令加密
     * @param userPass    打开pdf密码
     * @param ownerPass   编辑pdf密码
     * @param permissions 权限        example: PdfWriter.ALLOW_PRINTING
     * @return
     * @throws Exception
     */
    public static boolean exitPdf(InputStream inputStream, Map<String, String> dataParamMap, Map<String, Image> imgParamMap, OutputStream outputStream, boolean encryption, String userPass, String ownerPass, int permissions) throws Exception{
        BaseFont baseFont = BaseFont.createFont();
        PdfReader pdfReader = new PdfReader(inputStream);
        PdfStamper pdfStamper = new PdfStamper(pdfReader, outputStream);
        AcroFields form = pdfStamper.getAcroFields();
        form.addSubstitutionFont(baseFont);
        // 写入数据
        if (dataParamMap != null) {
            for (String key : dataParamMap.keySet()) {
                String value = dataParamMap.get(key);
                //key对应模板数据域的名称
                form.setField(key, value);
            }
        }
        if (imgParamMap != null) {
            for (Map.Entry<String, Image> entry:imgParamMap.entrySet()) {
                String key = entry.getKey();
                Image value = entry.getValue();
                //添加图片
                int pageNo = form.getFieldPositions(key).get(0).page;
                Rectangle signRect = form.getFieldPositions(key).get(0).position;
                float x = signRect.getLeft();
                float y = signRect.getBottom();
                PdfContentByte under = pdfStamper.getOverContent(pageNo);
                //设置图片大小
                value.scaleAbsolute(signRect.getWidth(), signRect.getHeight());
                //设置图片位置
                value.setAbsolutePosition(x, y);

                under.addImage(value);
            }
        }
        pdfStamper.setFormFlattening(true);
        if (encryption) {
            pdfStamper.setEncryption(true, userPass, ownerPass, permissions);
        }
        pdfStamper.close();
        outputStream.close();
        return true;
    }

    public static boolean exitPdf(PdfParam pdfParam) throws Exception{
        BaseFont baseFont = BaseFont.createFont();
        PdfReader pdfReader = new PdfReader(pdfParam.getInputStream());
        PdfStamper pdfStamper = new PdfStamper(pdfReader, pdfParam.getOutputStream());
        AcroFields form = pdfStamper.getAcroFields();
        form.addSubstitutionFont(baseFont);
        // 写入数据
        if (pdfParam.getDataParamMap() != null) {
            for (String key : pdfParam.getDataParamMap().keySet()) {
                String value = pdfParam.getDataParamMap().get(key);
                //key对应模板数据域的名称
                form.setField(key, value);
            }
        }
        if (pdfParam.getImgParamMap() != null) {
            for (Map.Entry<String, Image> entry:pdfParam.getImgParamMap().entrySet()) {
                String key = entry.getKey();
                Image value = entry.getValue();
                List<AcroFields.FieldPosition> fieldPositions = form.getFieldPositions(key);
                if (fieldPositions != null) {
                    for (AcroFields.FieldPosition fieldPosition:fieldPositions) {
                        //添加图片
                        Rectangle signRect = fieldPosition.position;
                        PdfContentByte under = pdfStamper.getOverContent(fieldPosition.page);
                        //设置图片大小
                        value.scaleAbsolute(signRect.getWidth(), signRect.getHeight());
                        //设置图片位置
                        value.setAbsolutePosition(signRect.getLeft(), signRect.getBottom());
                        under.addImage(value);
                    }
                }
            }
        }
        pdfStamper.setFormFlattening(true);
        if (pdfParam.isEncryption()) {
            pdfStamper.setEncryption(true, pdfParam.getUserPass(), pdfParam.getOwnerPass(), pdfParam.getPermissions());
        }

        pdfStamper.close();
        pdfParam.close();
        return true;
    }

    static class PdfParam {

        private InputStream inputStream;   // pdf文件流
        private OutputStream outputStream; // pdf输出流

        private String title;    // 标题
        private String author;   // 作者
        private String subject;  // 主题
        private String keywords; // 关键字
        private String creator;  // 创建者

        private Map<String, String> dataParamMap; // 表单参数
        private Map<String, Image> imgParamMap;   // 表单域图片

        private boolean encryption; // 是否设置权限
        private String userPass;    // 使用者密码
        private String ownerPass;   // 所有者密码
        private int permissions;    // 权限        example: PdfWriter.ALLOW_PRINTING

        public PdfParam(InputStream inputStream, OutputStream outputStream) {
            this.inputStream = inputStream;
            this.outputStream = outputStream;
        }

        public void close() {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        public InputStream getInputStream() {
            return inputStream;
        }

        public void setInputStream(InputStream inputStream) {
            this.inputStream = inputStream;
        }

        public OutputStream getOutputStream() {
            return outputStream;
        }

        public void setOutputStream(OutputStream outputStream) {
            this.outputStream = outputStream;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getAuthor() {
            return author;
        }

        public void setAuthor(String author) {
            this.author = author;
        }

        public String getSubject() {
            return subject;
        }

        public void setSubject(String subject) {
            this.subject = subject;
        }

        public String getKeywords() {
            return keywords;
        }

        public void setKeywords(String keywords) {
            this.keywords = keywords;
        }

        public String getCreator() {
            return creator;
        }

        public void setCreator(String creator) {
            this.creator = creator;
        }

        public Map<String, String> getDataParamMap() {
            return dataParamMap;
        }

        public void setDataParamMap(Map<String, String> dataParamMap) {
            this.dataParamMap = dataParamMap;
        }

        public Map<String, Image> getImgParamMap() {
            return imgParamMap;
        }

        public void setImgParamMap(Map<String, Image> imgParamMap) {
            this.imgParamMap = imgParamMap;
        }

        public boolean isEncryption() {
            return encryption;
        }

        public void setEncryption(boolean encryption) {
            this.encryption = encryption;
        }

        public String getUserPass() {
            return userPass;
        }

        public void setUserPass(String userPass) {
            this.userPass = userPass;
        }

        public String getOwnerPass() {
            return ownerPass;
        }

        public void setOwnerPass(String ownerPass) {
            this.ownerPass = ownerPass;
        }

        public int getPermissions() {
            return permissions;
        }

        public void setPermissions(int permissions) {
            this.permissions = permissions;
        }
    }

}
